package com.newlink.building.push

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.text.TextUtils
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import com.alibaba.android.arouter.core.LogisticsCenter
import com.alibaba.android.arouter.launcher.ARouter
import com.alibaba.sdk.android.push.AliyunMessageIntentService
import com.alibaba.sdk.android.push.notification.CPushMessage
import com.newlink.building.common_base.constant.Base_Constant
import com.newlink.building.common_base.constant.NL_Key
import com.newlink.building.common_base.constant.Base_RouterPath
import com.newlink.building.common_base.utils.NLog
import com.newlink.building.common_base.utils.Base_Preference
import com.newlink.building.obfuscation.Module_Obfuscation_ObfuscationHelper
import com.newlink.building.obfuscation.Module_Obfuscation_ObfuscationInvoker
import org.json.JSONException
import org.json.JSONObject


open class MessageIntentService : AliyunMessageIntentService() {
    private val requestCode: Int = 65
    private val callRequestCode: Int = 1002
    private val pushCallMsgMap: MutableMap<String?, String?> = mutableMapOf()

    //默认缓存第一次推送的aid,防止用户没有从通知点入或者划走通知的情况
    private var firstCallPushRemoteAid: String by Base_Preference(Base_Constant.PUSH_CALL_REMOTE_AID, "")

    companion object {
        private const val MSG_SYSTEM: String = "1"//系统消息
        private const val MSG_PROPERTY: String = "2"//物业消息
        private const val MSG_SECURITY: String = "3"//安防消息
        private const val MSG_INCOMING: String = "4"//来电消息

        private const val OFFLINE_INCOMING_CALL_TAG = "OICT"
        private const val OFFLINE_ALARM_TAG = "ALARM"
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // 推送服务启动时的混淆
        Module_Obfuscation_ObfuscationHelper.onMethodEnter("MessageIntentService", "onStartCommand")
        Module_Obfuscation_ObfuscationInvoker.invokeRandom(intent?.action?.hashCode() ?: 0)

        Log.e("[MessageIntentService]", "onStartCommand action:${intent?.action}")
        if (intent?.action == Base_Constant.ACTION_CANCEL_PUSH_CALL_NOTIFICATION) {
            cancelCallNotification(null)
            firstCallPushRemoteAid = ""
        } else if (intent?.action == Base_Constant.ACTION_CUSTOM_BACKGROUD_ALARM_NOTIFICATION) {
            val alarmTitle = intent?.getStringExtra("alarm_title")
            val alarmDesc = intent?.getStringExtra("alarm_desc")
            Log.e(
                "[MessageIntentService]",
                "ACTION_CUSTOM_BACKGROUD_ALARM_NOTIFICATION  alarmTitle:$alarmTitle alarmDesc:$alarmDesc"
            )
            if (!alarmTitle.isNullOrEmpty() && !alarmDesc.isNullOrEmpty()) {
                sendNotification(alarmTitle, alarmDesc, MSG_SECURITY)
            }

        }
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onNotificationOpened(
        context: Context?,
        title: String?,
        summary: String?,
        extraMap: String?
    ) {
        NLog.e(
            "[MessageIntentService] onNotificationOpened: $title----$summary----$extraMap"
        )
    }

    override fun onNotificationRemoved(context: Context?, messageId: String?) {
        NLog.e("[MessageIntentService] onNotificationRemoved: $messageId")
    }

    // 当应用在后台时，的推送通知方法
    override fun onNotification(
        context: Context?,
        title: String?,
        summary: String?,
        extraMap: MutableMap<String, String>?
    ) {
        NLog.e("[MessageIntentService]  onNotification: $title----$summary -- $extraMap")
        val msgType = extraMap?.get("msgType")
        msgType?.let {
            when (it) {
                "4" -> {
                    // 离线来电
                    sendNotification2(title!!, summary!!, extraMap)
                    jumpToFcmCall(extraMap)
                }

                "5" -> {
                    //  取消来电
                    if (extraMap != null) {
                        cancelFcmCall(extraMap)
                        cancelCallNotification(extraMap)
                    }
                }

                else -> {
                    sendNotification(title!!, summary!!, it)
                }
            }
        }
    }

    // 当应用在后台时：推送消息的回调方法
    override fun onMessage(context: Context?, cPushMessage: CPushMessage?) {

    }

    override fun onNotificationClickedWithNoAction(
        context: Context?,
        title: String?,
        summary: String?,
        extraMap: String?
    ) {
        // 通知点击处理时的混淆
        Module_Obfuscation_ObfuscationInvoker.invokeRandom(extraMap?.hashCode() ?: System.currentTimeMillis())

        NLog.e("[MessageIntentService] onNotificationClickedWithNoAction.....$extraMap")
        try {
            // 如果JSON是对象
            val jsonObject = JSONObject(extraMap)
            val type: String = jsonObject.getString("msgType")
            NLog.e("[MessageIntentService] 推送 >>> onNotificationClickedWithNoAction.....$type")
            if (TextUtils.equals(type, MSG_SYSTEM)) {
                ARouter.getInstance().build(Base_RouterPath.PATH_MSG_TAB)
                    .withInt("PAGE", 1)
                    .navigation()
            } else if (TextUtils.equals(type, MSG_PROPERTY)) {
                ARouter.getInstance().build(Base_RouterPath.PATH_MSG_TAB)
                    .navigation()
            } else if (TextUtils.equals(type, MSG_SECURITY)) {
                ARouter.getInstance().build(Base_RouterPath.PATH_NOTIFY)
                    .withInt(NL_Key.TAB_INDEX, 2)
                    .withInt(NL_Key.SUB_TAB_INDEX, 2)
                    .navigation()
            } else if (TextUtils.equals(type, MSG_INCOMING)) {
                ARouter.getInstance().build(Base_RouterPath.PATH_NOTIFY)
                    .navigation()
            }

        } catch (e: JSONException) {
            e.printStackTrace()
        }

    }

    // 应用处于前台时，通知到达回调。注意:该方法仅对自定义样式通知有效
    override fun onNotificationReceivedInApp(
        context: Context?,
        title: String?,
        summary: String?,
        extraMap: MutableMap<String, String>?,
        openType: Int,
        openActivity: String?,
        openUrl: String?
    ) {
        NLog.e("[MessageIntentService]  onNotificationReceivedInApp: $title----$summary")

    }

    /**
     * 发送通知
     * @param contentTitle 通知标题
     * @param contentText 通知内容
     */
    private fun sendNotification1(contentTitle: String?, contentText: String?) {
        val channelId = getString(R.string.push_notification_channel_id)
        val channelName =
            getString(R.string.push_notification_channel_name, getString(R.string.app_name_smart))
        val defaultNotifySound: Uri =
            RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
        val intent = Intent("com.vdroid.dooraccess.action.aliyun")
        val pendingIntent =
            PendingIntent.getActivity(
                this, requestCode, intent,
                PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
            )
        val notificationBuilder: NotificationCompat.Builder =
            NotificationCompat.Builder(this, channelId)
        notificationBuilder.setContentTitle(contentTitle)
            .setContentText(contentText)
            .setSmallIcon(android.R.mipmap.sym_def_app_icon)
            .setLargeIcon(
                BitmapFactory.decodeResource(
                    resources,
                    android.R.mipmap.sym_def_app_icon
                )
            )
            .setAutoCancel(true)
            .setSound(defaultNotifySound)
            .setContentIntent(pendingIntent)
        val notificationManager =
            applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
            val notificationChannel = NotificationChannel(
                channelId,
                channelName,
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(notificationChannel)
        }

        notificationManager.notify(requestCode, notificationBuilder.build())
    }

    private fun sendNotification2(
        contentTitle: String,
        contentText: String,
        extraMap: MutableMap<String, String>?
    ) {
        val channelId = getString(R.string.push_notification_channel_id)
        val channelName =
            getString(R.string.push_notification_channel_name, getString(R.string.app_name_smart))
//        val channelName =
//            getString(R.string.default_notification_channel_name)
        val notificationManager =
            applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
//        val defaultNotifySound: Uri =
//            RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
//        val audioAttributes: AudioAttributes = AudioAttributes.Builder()
//            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
//            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
//            .build()
//        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
//            val notificationChannel = NotificationChannel(
//                channelId,
//                channelName,
//                NotificationManager.IMPORTANCE_LOW
//            )
//            notificationChannel.description = "Incoming call"
//            // 设置通知出现时的闪灯（如果 android 设备支持的话）
//            notificationChannel.enableLights(true)
//            notificationChannel.lightColor = Color.RED
//            // 设置通知出现时的震动（如果 android 设备支持的话）
//            notificationChannel.enableVibration(true)
//            notificationChannel.setSound(defaultNotifySound, audioAttributes)
//            notificationChannel.vibrationPattern = longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)
//            notificationChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
//            notificationManager.createNotificationChannel(notificationChannel)
//        }


        val intent = getDestinationIntent("4", extraMap, contentTitle)

        //requestCode用对端aid标记,区分PendingIntent的跳转
        val pendingIntent =
            PendingIntent.getActivity(
                this, convertExtraToRequestCode(extraMap?.get("from")), intent,
                PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
            )
        val notificationBuilder: NotificationCompat.Builder =
            NotificationCompat.Builder(this, channelId)
//        val title = "[$contentTitle] " + getString(R.string.call)
//        val content = getString(R.string.call_info, contentText)
        NLog.e("MessageIntentService content is :$$contentTitle :::  $contentText")
        notificationBuilder.setContentTitle(contentTitle)
            .setContentText(contentText)
            .setSmallIcon(R.mipmap.logo)
            .setAutoCancel(true)
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .setContentIntent(pendingIntent)
            .setColor(ContextCompat.getColor(this, R.color.colorPrimary))

        NLog.e("[MessageIntentService] >>>>>>>>>>> sendNotification222")
        notificationManager.notify(
            "$OFFLINE_INCOMING_CALL_TAG-${extraMap?.get("callId")}",
            callRequestCode,
            notificationBuilder.build()
        )
    }

    private fun convertExtraToRequestCode(from: String?): Int {
        val intentRequestCode = if (from != null) {
            try {
                from!!.toInt()
            } catch (e: Exception) {
                requestCode
            }
        } else {
            requestCode
        }
        return intentRequestCode
    }

    private fun cancelCallNotification(extraMap: MutableMap<String, String>?) {
        NLog.e("[MessageIntentService] >>>>>>>>>>> cancelCallNotification extraMap:$extraMap pushCallMsgMap:$pushCallMsgMap")
        //默认推送和取消是成对出现的 异常情况通过ACTION_CANCEL_PUSH_CALL_NOTIFICATION中清理
        if (extraMap == null) {
            for (entry in pushCallMsgMap) {
                cancel(callRequestCode, "$OFFLINE_INCOMING_CALL_TAG-${entry.key}")
            }
            pushCallMsgMap.clear()
        } else {
            cancel(callRequestCode, "$OFFLINE_INCOMING_CALL_TAG-${extraMap["callId"]}")
            pushCallMsgMap.remove(extraMap?.get("callId"))
        }
//        cancel(callRequestCode , OFFLINE_INCOMING_CALL_TAG)
    }

    private fun cancel(id: Int, tag: String? = null) {
        NLog.e("[MessageIntentService] >>>>>>>>>>> id : $id  , tag : $tag")
        val notificationManager =
            applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.cancel(tag, id)
    }

    private fun sendNotification(contentTitle: String, contentText: String, msgType: String) {
        val channelId = getString(R.string.push_notification_channel_id)
        val channelName =
            getString(R.string.push_notification_channel_name, getString(R.string.app_name_smart))
        //        val channelId = "DoorAccessId-123456789"
        //        val channelName = "DoorAccessName-123456789"
        val defaultNotifySound: Uri =
            RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
//        val postcard = ARouter.getInstance().build(RouterPath.PATH_NOTIFY)
//        LogisticsCenter.completion(postcard)
//        val intent = Intent(this, postcard.destination)
        val intent = getDestinationIntent(msgType)
        var requestCode = intent.hashCode()

        val pendingIntent =
            PendingIntent.getActivity(
                this, requestCode, intent,
                PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
            )
        val notificationBuilder: NotificationCompat.Builder =
            NotificationCompat.Builder(this, channelId)
        notificationBuilder.setContentTitle(contentTitle)
            .setContentText(contentText)
            .setSmallIcon(R.mipmap.logo)
            .setSound(defaultNotifySound)
            .setAutoCancel(true)
            .setContentIntent(pendingIntent)
            .setColor(ContextCompat.getColor(this, R.color.colorPrimary))
        val notificationManager =
            applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
            val notificationChannel = NotificationChannel(
                channelId,
                channelName,
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(notificationChannel)
        }
        NLog.e("[MessageIntentService] >>>>>>>>>>> sendNotification")
//        notificationManager.notify("OFFLINE_ALARM_TAG_${System.currentTimeMillis()}", requestCode, notificationBuilder.build())
        notificationManager.notify(
            "OFFLINE_ALARM_TAG_${System.currentTimeMillis()}",
            requestCode,
            notificationBuilder.build()
        )
    }

    fun getDestinationIntent(
        type: String,
        extraMap: MutableMap<String, String>? = mutableMapOf(),
        contentTitle: String = ""
    ): Intent {
        return if (TextUtils.equals(type, MSG_SYSTEM)) {
            val postcard = ARouter.getInstance().build(Base_RouterPath.PATH_MSG_TAB)
            LogisticsCenter.completion(postcard)
            Intent(this, postcard.destination).apply {
                putExtra("PAGE", 1)
            }

        } else if (TextUtils.equals(type, MSG_PROPERTY)) {
            val postcard = ARouter.getInstance().build(Base_RouterPath.PATH_MSG_TAB)
            LogisticsCenter.completion(postcard)
            Intent(this, postcard.destination)
        } else if (TextUtils.equals(type, MSG_SECURITY)) {
            val postcard = ARouter.getInstance().build(Base_RouterPath.PATH_NOTIFY)
            LogisticsCenter.completion(postcard)
            Intent(this, postcard.destination).apply {
                putExtra(NL_Key.TAB_INDEX, 3)
                putExtra(NL_Key.SUB_TAB_INDEX, 2)
            }
        } else if (TextUtils.equals(type, MSG_INCOMING)) {
            val callId = extraMap?.get("callId")
            val from = extraMap?.get("from")
            pushCallMsgMap[callId] = from
            if (firstCallPushRemoteAid.isNullOrEmpty()) {
                firstCallPushRemoteAid = from.orEmpty()
            }
            NLog.e("MessageIntentService MSG_INCOMING  callId :$callId from :$from firstCallPushRemoteAid:$firstCallPushRemoteAid")
            val postcard = ARouter.getInstance().build(Base_RouterPath.PATH_NOTIFY)
            LogisticsCenter.completion(postcard)
            Intent(this, postcard.destination).apply {
                putExtra("push-callId", callId)
                putExtra("push-from", from)
                putExtra("push-title", contentTitle)
            }
        } else {
            val postcard = ARouter.getInstance().build(Base_RouterPath.PATH_NOTIFY)
            LogisticsCenter.completion(postcard)
            Intent(this, postcard.destination)
        }
    }

    private fun jumpToFcmCall(extraMap: MutableMap<String, String>?) {
        try {
            val title = extraMap?.get("title")
            val callId = extraMap?.get("callId")
            val message = extraMap?.get("message")
            ARouter.getInstance().build(Base_RouterPath.PATH_FCMINCOMINGCALL)
                .withString("fcm_title", title)
                .withString("fcm_message", message)
                .withString("fcm_callId", callId)
                .navigation()
        } catch (e: Exception) {
            NLog.e("[MessageIntentService] jump to fcmcall failed. $e")
        }
    }

    private fun cancelFcmCall(extraMap: MutableMap<String, String>?) {
        try {
            val title = extraMap?.get("title")
            val callId = extraMap?.get("callId")
            val message = extraMap?.get("message")
            if (pushCallMsgMap.containsKey(callId)) {
                ARouter.getInstance().build(Base_RouterPath.PATH_FCMINCOMINGCALL)
                    .withString("fcm_title", title)
                    .withString("fcm_message", message)
                    .withString("fcm_callId", callId)
                    .withBoolean("fcm_cancel", true)
                    .navigation()
            }

        } catch (e: Exception) {
            NLog.e("[MessageIntentService] cancel fcmcall failed. $e")
        }
    }
}